#!/usr/bin/env ruby
#
# Created by Jerry Luk on 2008-05-09
# Copyright (c) 2008. All rights reserved.

module Google
  # GContactsService extends the GDataService to streamline Google Contacts operations
  # 
  # == Authentication
  # 
  # GContactsService supports two kind of authentications: AuthSub and client login.
  # 
  # ==== Using AuthSub
  # 
  # First you have to generate the AuthSub url
  #   service = Google::::GContactsService.new
  #   auth_sub_url = service.generate_auth_sub_url('http://example.com/return_url')
  # When user go to the auth_sub_url and approves the service, google will return the token
  # to the url you specify with the parameter 'token'. In the example, it will be
  # <tt>http://localhost:3000/?token=the_auth_token</tt>
  # Set the token the service object to use the GCalService
  #   service.auth_token = auth_token
  # The token is a one-time token, if you want to get a long-lived session token, do::
  #   service.upgrade_auth_token
  # Now that you have the session token, you can save it
  #   session_token = service.session_token
  # To use the session token later
  #   service.session_token = session_token
  # 
  # ==== Use Client Login
  # 
  # Call the client_login method with the username and password
  #   service.client_login('user@gmail.com', 'password', 'http://www.example.com')
  # 
  # == Examples
  # 
  #   # Prints all the contact names
  #   contact_list = service.get_contact_list
  #   contact_list.contacts.each { |c| puts c.name }
  # 
  #   # CRUD an contact
  #   contact = Google::::GContact.new
  #   contact.name = "Jerry Luk"
  #   contact = service.insert_contact(contact)
  #   contact = service.get_contact(contact.atom_id)
  #   contact.name = "Jerry T Luk"
  #   contact = service.update_contact(contact)
  #   service.delete_contact(contact)
  #
  class GContactsService < GDataService
    DEFAULT_URI = '/m8/feeds/contacts/default/base'
    def initialize()
      super
      @server = 'http://www.google.com'
      @scope = 'http://www.google.com/m8/feeds/'
    end    
    
    # Authenticates the user and sets the GData Auth token for using the
    # Google Contact services
    # 
    # Login retreives a temporary auth token which must be used with all
    # requests to GData services. The auth token is stored in the GData client
    # object
    # 
    # ==== Options
    # +username+:: The username of the account
    # +password+:: The password of the account
    # +source+:: Optional. The URL for your service
    # +account_type+:: Optional. The default is 'HOSTED_OR_GOOGLE'
    #
    def client_login(username, password, source=nil, account_type=nil)
      super(username, password, 'cp', source, account_type)
    end
    
    # Gets the user's contact list
    #  See http://code.google.com/apis/contacts/developers_guide_protocol.html#Retrieving
    #  for query parameters
    # 
    # ==== Options
    # +uri+:: Optional. The URI of the contact list.
    # +params+:: Additional URL parameters to be included
    #         in the URI. These are translated into query arguments
    #         in the form '&dict_key=value&...'.
    #         (e.g., ) <tt>{'max-results': '250'}</tt> would yield a
    #         parameter <tt>&max-results=250</tt>
    #
    def get_contact_list(uri=DEFAULT_URI, params={})
      GContactList.new(self.get(uri, params))
    end
    
    # Gets the contact given a URI
    # 
    # ==== Options
    # +uri+:: The URI of the contact. It is usually the atom_id
    # +params+:: Additional URL parameters to be included
    #         in the URI.
    #
    def get_contact(uri, params={})
      GContact.new(self.get(uri, params))
    end
    
    # Adds a contact
    #
    # ==== Options
    # +new_event+:: XML or GContact which is to be added
    # +uri+:: Optional. The contacts feed where the contact
    #         to be inserted
    # +params+:: Additional URL parameters to be included
    #            in the URI.
    #
    def insert_contact(new_contact, uri=DEFAULT_URI, params={})
      GContact.new(self.post(new_contact, uri, params))
    end
    
    # Updates an existing event on the Google Calendar
    #
    # ==== Options
    # +updated_contact+:: XML or GContact which is to be updated
    # +params+:: Additional URL parameters to be included
    #            in the URI.
    #
    def update_contact(updated_contact, params={})
      GContact.new(self.put(updated_contact, updated_contact.edit_link, params))
    end
    
    # Removes a contact with the specified ID
    #
    # ==== Options
    # +edit_uri_or_contact+:: The edit URL of the entry or the GContact
    #                         which is to be deleted.
    # +params+:: Additional URL parameters to be included
    #            in the URI.
    #
    def delete_contact(edit_uri_or_contact, params={})
      edit_uri_or_contact = edit_uri_or_contact.edit_link if edit_uri_or_contact.kind_of? GContact
      self.delete(edit_uri_or_contact, params)
    end
  end
end